package org.farm2.service.controller;

import com.farm2.lucene.Farm2LuceneFace;
import com.farm2.lucene.document.FarmDocument;
import com.farm2.lucene.dto.IndexInfoDto;
import com.farm2.lucene.inter.Farm2LuceneIndexInter;
import com.farm2.lucene.utils.FarmLuceneUtils;
import org.farm2.auth.dto.KeyValueDto;
import org.farm2.base.db.process.FarmProcessTypeEnum;
import org.farm2.base.db.process.FarmProcessUtils;
import org.farm2.service.event.utils.KnowIndexDocumentBuilder;
import org.farm2.service.lucene.doc.KnowIndexDocument;
import org.farm2.skc.enums.KnowFileTypeEnum;
import org.farm2.skc.service.SkcKnowServiceInter;
import org.farm2.tools.db.DataQuery;
import org.farm2.tools.db.DataResult;
import org.farm2.tools.db.ResultDataHandle;
import org.farm2.tools.files.Farm2FileUtils;
import org.farm2.tools.files.Farm2ProcessState;
import org.farm2.tools.web.FarmResponseCode;
import org.farm2.tools.web.FarmResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 索引管理
 *
 * @author cbtg自动生成  2025-1-2 22:01:57
 */
@RestController
@RequestMapping("/api/lucene")
public class WebLuceneController {
    @Autowired
    private SkcKnowServiceInter skcKnowServiceImpl;
    @Autowired
    private KnowIndexDocumentBuilder snowIndexDocumentBuilder;
    /**
     *
     * @return
     */
    @PreAuthorize("@farmAction.has('lucene.info')")
    @PostMapping("/info")
    public FarmResponseResult info() {
        Map<String, IndexInfoDto> infos = new HashMap<>();
        IndexInfoDto textIndex = new IndexInfoDto();
        textIndex.setTitle("文本索引");
        textIndex.setSize(FarmLuceneUtils.getIndexSize(FarmLuceneUtils.getLuceneIndexFilePath()));
        textIndex.setPath(FarmLuceneUtils.getLuceneIndexFilePath());
        infos.put("text", textIndex);
        IndexInfoDto vectorIndex = new IndexInfoDto();
        vectorIndex.setTitle("向量索引");
        vectorIndex.setSize(FarmLuceneUtils.getIndexSize(FarmLuceneUtils.getLuceneEmbeddingFilePath()));
        vectorIndex.setPath(FarmLuceneUtils.getLuceneEmbeddingFilePath());
        infos.put("vector", vectorIndex);
        return FarmResponseResult.getInstance(FarmResponseCode.SUCESS, infos);
    }


    @PreAuthorize("@farmAction.has('lucene.index')")
    @PostMapping("/index")
    public FarmResponseResult index(@RequestBody KeyValueDto key) throws IOException {
        if (key.getKey().equals("text")) {
            FarmProcessUtils.setProcess(key.getKey(), FarmProcessTypeEnum.CONVERT_INDEX, 1, "开始");
            new Thread(() -> {
                reIndexAllKnow(key.getKey());
            }).start();
        }
        if (key.getKey().equals("vector")) {
            FarmProcessUtils.setProcess(key.getKey(), FarmProcessTypeEnum.CONVERT_INDEX, 1, "开始");
            new Thread(() -> {
                reVectorAllKnow(key.getKey());
            }).start();
        }
        return FarmResponseResult.getInstance(FarmResponseCode.SUCESS);
    }


    /**
     * 重新创建所有知识的向量索引
     */
    private void reVectorAllKnow(String key) {
        {//创建知识索引
            DataQuery query = new DataQuery();
            query.setPageSize(100);
            int page = 1;
            Farm2LuceneIndexInter indexs = Farm2LuceneFace.getIndexService(FarmLuceneUtils.getLuceneEmbeddingFilePath());
            while (true) {
                List<FarmDocument> docs = new ArrayList<>();
                query.setPage(page);
                page++;
                DataResult result = skcKnowServiceImpl.searchSkcKnow(query);
                if (result.getData().size() <= 0) {
                    break;
                } else {
                    final Integer[] n = {0};
                    result.runDataHandle(new ResultDataHandle() {
                        @Override
                        public void handle(Map<String, Object> row) {
                            try {
                                //缓存处理进度
                                FarmProcessUtils.setProcess(key, FarmProcessTypeEnum.CONVERT_INDEX, result.getPage() * 100 / result.getTotalPage() - 1, result.getPage() + "/" + result.getTotalPage() + "(当前处理:" + (++n[0]) + "/" + result.getData().size() + ")");
                                String knowid = (String) row.get("ID");
                                List<String> files = skcKnowServiceImpl.getKnowFiles(knowid, null);
                                for (String fileid : files) {
                                    docs.addAll(snowIndexDocumentBuilder.getVectorDoc(knowid, fileid));
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
                indexs.createIndex(docs);
            }
            FarmProcessUtils.setProcessEnd(key, FarmProcessTypeEnum.CONVERT_INDEX, "完成");
        }
    }


    /**
     * 重新创建所有知识的索引
     */
    private void reIndexAllKnow(String key) {
        {//创建知识索引
            DataQuery query = new DataQuery();
            query.setPageSize(100);
            int page = 1;
            Farm2LuceneIndexInter indexs = Farm2LuceneFace.getIndexService();
            while (true) {
                List<FarmDocument> docs = new ArrayList<>();
                query.setPage(page);
                page++;
                DataResult result = skcKnowServiceImpl.searchSkcKnow(query);
                if (result.getData().size() <= 0) {
                    break;
                } else {
                    final Integer[] n = {0};
                    result.runDataHandle(new ResultDataHandle() {
                        @Override
                        public void handle(Map<String, Object> row) {
                            try {
                                //缓存处理进度
                                FarmProcessUtils.setProcess(key, FarmProcessTypeEnum.CONVERT_INDEX, result.getPage() * 100 / result.getTotalPage() - 1, result.getPage() + "/" + result.getTotalPage() + "(当前处理:" + (++n[0]) + "/" + result.getData().size() + ")");
                                String knowid = (String) row.get("ID");
                                KnowIndexDocument doc = snowIndexDocumentBuilder.getKnowDoc(knowid);
                                if (doc != null) {
                                    docs.add(doc.getDoc());
                                    List<String> files = skcKnowServiceImpl.getKnowFiles(knowid, KnowFileTypeEnum.KNOW_FILE.getKey());
                                    for (String fileid : files) {
                                        try {
                                            KnowIndexDocument filedoc = snowIndexDocumentBuilder.getFileDoc(knowid, fileid);
                                            if (filedoc != null) {
                                                docs.add(filedoc.getDoc());
                                            }
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
                indexs.createIndex(docs);
            }
            FarmProcessUtils.setProcessEnd(key, FarmProcessTypeEnum.CONVERT_INDEX, "完成");
        }
    }


    @PreAuthorize("@farmAction.has('lucene.del')")
    @PostMapping("/del")
    public FarmResponseResult del(@RequestBody KeyValueDto key) throws IOException {
        if (key.getKey().equals("text")) {
            //删除文本索引
            if (Path.of(FarmLuceneUtils.getLuceneIndexFilePath()).toFile().exists()) {
                Farm2FileUtils.deleteFolderRecursively(Path.of(FarmLuceneUtils.getLuceneIndexFilePath()));
            }
        }

        if (key.getKey().equals("vector")) {
            //删除向量索引
            if (Path.of(FarmLuceneUtils.getLuceneIndexFilePath()).toFile().exists()) {
                Farm2FileUtils.deleteFolderRecursively(Path.of(FarmLuceneUtils.getLuceneEmbeddingFilePath()));
            }
        }
        return FarmResponseResult.getInstance(FarmResponseCode.SUCESS);
    }
}
